-- DungeonActionM
-- created by panyl
-- 迷宫操作行为

module("DungeonActionM", package.seeall);

local actions = {};
local rules = {};

local needSave;

-- 载入配置表
local _init = false;
local loadCsv = function()
    if _init then return end
    _init = true;

    -- 转换下dungeon_action信息表
    local dungeon_action_CSV = get_dungeon_action_CSV();
    for i = 1, #dungeon_action_CSV do
        actions[dungeon_action_CSV[i].action] = dungeon_action_CSV[i];
    end

    dungeon_action_CSV = {};
end

-- 模块初始化操作
function init()
    if not _init then
        loadCsv();

        -- 载入所有的规则处理子模块
        rules = LOAD_PATH("game/logic/module/dungeon_actions");
    end
end

-- 检索
function query(cmd, path)
    local m = actions[cmd];

    if not m or not path then
        return m;
    end

    return m[path];
end

-- 客户端执行一条action指令
-- TODO: 待所有指令都调整完毕后，需要把客户端验证的流程也整合进来
function go(cmd, pos, data, extra)
    local record = {["cmd"] = cmd, ["pos"] = pos, ["data"] = data, ["extra"] = extra, };
    DungeonLogM.addRecord(record);
    DungeonDebugM.addAction({["cmd"] = cmd, ["pos"] = pos, ["data"] = data, ["extra"] = extra, });

    local mod = rules[cmd];
    Profiler.funcBegin("action:" .. cmd);
    local ret, added = mod.doAction({ ["pos"] = pos, ["data"] = data }, extra);
    if ret ~= false and true ~= added then
        -- 部分指令已经自行添加了action，就不重复添加
        -- 执行成功了，添加到同步队列中
        DungeonM.addAction({ ["cmd"] = cmd, ["data"] = data, ["pos"] = pos, });
    end

    if ret ~= false then
        -- 标记一下是有效的action
        record["done"] = 1;
    end

    -- 如果需要即时保存一下
    if not isVerifyClient() and needSave then
        needSave = false;

        go("save_dungeon");
    end

    Profiler.funcEnd("action:" .. cmd);
    return ret;
end

-- 一个操作，一般都是玩家做的操作
function doActions(actions)
    for index = 1, #actions do
        local action = actions[index];

        local cmd    = action.cmd;
        local times  = action.times or 1;

        DungeonLogM.addLog("action: " .. cmd .. " " .. tableToString(action));
        assert(cmd);

        -- 子模块处理
        for i = 1, times do
            local status, err = xpcall(function() go(cmd, action.pos, action.data); end, __G__TRACKBACK__);
            if not status then
                DungeonLogM.addLog("action error:\n" .. err);
            end
        end
    end
end

-- 重播
function replayActions(actions, step, speed)
    local action = actions[step];
    local cmd    = action.cmd;
    local times  = action.times or 1;
    local interval = speed / 1000;

    -- 开始迷宫、进出副本需要时间比较长
    if cmd == "start_dungeon" or cmd == "start_instance" or cmd == "leave_instance" then
        interval = 3;
    end

    -- 子模块处理
    for i = 1, times do
        local mod = rules[cmd];
        local status, err = xpcall(function() mod.doAction(action); end, __G__TRACKBACK__);
        if not status then
            print(err);
        end

        EventMgr.fire(event.PLAYER_MOVE, action.pos);
    end

    if step >= #actions then
        replayFinish();

        return;
    end

    function nextStep()
        replayActions(actions, step + 1, speed);
    end

    -- 定时下一个操作
    ScheduleM.createScheme("replayActions" .. step, nextStep, interval, false);
end

function replayFinish()
    -- switchReplaying(false);

    DungeonM.switchState(DUNGEON_LEAVE);
end

-- 即可保存进度
function immediatelySave()
    needSave = true;
end
